﻿using LanguagePolish.EntityModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace LanguagePolish.Controls
{
    /// <summary>
    /// Логика взаимодействия для CalendarGrid.xaml
    /// </summary>
    public partial class MonthGrid : UserControl
    {
        public static readonly DependencyProperty MonthProperty =
          DependencyProperty.Register("Month", typeof(int),
          typeof(MonthGrid), new PropertyMetadata(DateTime.Now.Month, OnMonthChanged));
        
        public static readonly DependencyProperty YearProperty =
          DependencyProperty.Register("Year", typeof(int),
          typeof(MonthGrid), new PropertyMetadata(DateTime.Now.Year, OnYearChanged));

        public static readonly DependencyProperty LessonsProperty =
          DependencyProperty.Register("Lessons", typeof(IEnumerable<Lesson>),
          typeof(MonthGrid), new PropertyMetadata(null, OnLessonsChanged));

        public static readonly DependencyProperty EnableMenuProperty =
            DependencyProperty.Register("EnableMenu", typeof(bool), typeof(MonthGrid), new PropertyMetadata(true, OnEnableMenuChanged));

        private static void OnEnableMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MonthGrid g = (MonthGrid)d;
            g.InitCells();
        }

        public bool EnableMenu
        {
            get { return (bool)GetValue(EnableMenuProperty); }
            set { SetValue(EnableMenuProperty, value); }
        }
        
        public event EventHandler<AddLessonEventArgs> AddLesson;
        public event EventHandler<EditLessonEventArgs> EditLesson;
        public event EventHandler<RemoveLessonEventArgs> RemoveLesson;

        private static void OnMonthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MonthGrid g = (MonthGrid)d;
            g.InitCells();
        }

        private static void OnYearChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MonthGrid g = (MonthGrid)d;
            g.InitCells();
        }

        private static void OnLessonsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MonthGrid g = (MonthGrid)d;
            g.InitCells();
        }

        private int month = DateTime.Now.Month;
        public int Month
        {
            get { return (int)this.GetValue(MonthProperty); }
            set 
            {
                if (value == month)
                    return;
                this.SetValue(MonthProperty, value);
                InitCells();
            }
        }

        private int year = DateTime.Now.Year;
        public int Year
        {
            get { return (int)this.GetValue(YearProperty); }
            set 
            {
                if (value == month)
                    return;
                this.SetValue(YearProperty, value);
                InitCells();
            }
        }
        
        public IEnumerable<Lesson> Lessons
        {
            get { return (IEnumerable<Lesson>)this.GetValue(LessonsProperty); }
            set 
            {
                this.SetValue(LessonsProperty, value);
                InitCells();
            }
        }

        public MonthGrid()
        {
            InitializeComponent();
            InitCells();
        }

        private void InitDaysOfWeek()
        {
            grdMain.RowDefinitions.Add(new RowDefinition { Height = new GridLength(30) });
            for (int i = 0; i < 7; i++)
            {
                string dayName = GlobalSettings.DaysOfWeek[i];
                Label lblDay = new Label();
                lblDay.Content = dayName;
                Grid.SetColumn(lblDay, i + 1);
                Grid.SetRow(lblDay, 0);
                grdMain.Children.Add(lblDay);
            }
        }

        private void InitCells()
        {
            grdMain.RowDefinitions.Clear();
            grdMain.Children.Clear();
            InitDaysOfWeek();
            int firstDay = (int)(new DateTime(Year, Month, 1).DayOfWeek);
            firstDay = firstDay == 0 ? 6 : firstDay - 1;
            int dayInMonth = DateTime.DaysInMonth(Year, Month);
            int countOfWeek = (int)Math.Ceiling((firstDay + dayInMonth) / 7.0);
            for (int i = 0; i < countOfWeek; i++)
            {
                grdMain.RowDefinitions.Add(new RowDefinition());
            }
            // prev month
            if (firstDay != 0)
            {
                DateTime dt = new DateTime(Year, Month, 1);
                dt = dt.AddMonths(-1);
                int dayInMonthPrev = DateTime.DaysInMonth(dt.Year, dt.Month);
                int firstDayPrev = dayInMonthPrev - firstDay + 1;
                for (int d = firstDayPrev; d <= dayInMonthPrev; d++)
                {
                    int n = firstDay + d - dayInMonthPrev;
                    int i = (n - 1) / 7 + 1;
                    int j = (n - 1) % 7 + 1;
                    CalendarCell cell = new CalendarCell();
                    //cell.AddLesson += cell_AddLesson;
                    //cell.RemoveLesson += cell_RemoveLesson;
                    //cell.EditLesson += cell_EditLesson;
                    cell.Date = new DateTime(dt.Year, dt.Month, d);
                    cell.IsActiveDate = false;
                    Grid.SetColumn(cell, j);
                    Grid.SetRow(cell, i);
                    grdMain.Children.Add(cell);
                }
            }
            Random rnd = new Random();
            // current month
            for (int d = 1; d <= dayInMonth; d++)
            {
                int n = firstDay + d;
                int i = (n - 1) / 7 + 1;
                int j = (n - 1) % 7 + 1;
                CalendarCell cell = new CalendarCell();
                cell.AddLesson += cell_AddLesson;
                cell.RemoveLesson += cell_RemoveLesson;
                cell.EditLesson += cell_EditLesson;
                DateTime cellDate = new DateTime(Year, Month, d);
                cell.Date = cellDate;
                cell.IsActiveDate = true;
                cell.EnableMenu = EnableMenu;
                // add lessons for this date
                if (Lessons != null)
                {
                    var cellLessons = Lessons.Where(s => s.LessonDate != null && s.LessonDate.Value.Date.Equals(cellDate));
                    if (cellLessons != null && cellLessons.Any())
                    {
                        cell.CellItems = cellLessons.ToList();
                    }
                }
                Grid.SetColumn(cell, j);
                Grid.SetRow(cell, i);
                grdMain.Children.Add(cell);
            }
            // next month
            int lastDay = (int)(new DateTime(Year, Month, dayInMonth).DayOfWeek);
            lastDay = lastDay == 0 ? 6 : lastDay - 1;
            if (lastDay != 6)
            {
                DateTime dt = new DateTime(Year, Month, 1);
                dt = dt.AddMonths(1);
                for (int d = 1; d <= 7 - lastDay - 1; d++)
                {
                    int n = firstDay + dayInMonth + d;
                    int i = (n - 1) / 7 + 1;
                    int j = (n - 1) % 7 + 1;
                    CalendarCell cell = new CalendarCell();
                    //cell.AddLesson += cell_AddLesson;
                    //cell.RemoveLesson += cell_RemoveLesson;
                    //cell.EditLesson += cell_EditLesson;
                    cell.Date = new DateTime(dt.Year, dt.Month, d);
                    cell.IsActiveDate = false;
                    Grid.SetColumn(cell, j);
                    Grid.SetRow(cell, i);
                    grdMain.Children.Add(cell);
                }
            }
        }

        void cell_EditLesson(object sender, EditLessonEventArgs e)
        {
            if (EditLesson != null)
                EditLesson(this, e);
        }

        void cell_RemoveLesson(object sender, RemoveLessonEventArgs e)
        {
            if (RemoveLesson != null)
                RemoveLesson(this, e);
        }

        void cell_AddLesson(object sender, AddLessonEventArgs e)
        {
            if (AddLesson != null)
                AddLesson(this, e);
        }

    }
}
